﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections.ObjectModel;

namespace JacketEmblem.Crane.UnitTests.NUnitExtensions
{
    public class TreeConstructionDataFileReader : DataFileReader
    {
        private List<DataFileTestInfo> tests = new List<DataFileTestInfo>();

        public override ReadOnlyCollection<DataFileTestInfo> Tests
        {
            get { return tests.AsReadOnly(); }
        }

        public override void ReadDataFile(string fileName)
        {
            string[] dataFileLines = File.ReadAllLines(fileName);
            Dictionary<string, StringBuilder> components = InitializeBuilders();
            int currentLineIndex = 0;
            string currentLine = dataFileLines[currentLineIndex].Trim();
            while (currentLineIndex < dataFileLines.Length)
            {
                currentLineIndex = ReadToNextMarker(dataFileLines, currentLineIndex, components[currentLine]);
                if (currentLineIndex < dataFileLines.Length)
                {
                    currentLine = dataFileLines[currentLineIndex].Trim();
                }
                else
                {
                    currentLine = "#data";
                    components["#document"].AppendLine();
                }

                if (currentLine == "#data")
                {
                    List<object> argumentList = new List<object>();
                    argumentList.Add(components["#data"].ToString());
                    argumentList.Add(CreateExpectedErrorList(components["#errors"].ToString()));
                    argumentList.Add(components["#document"].ToString());
                    argumentList.Add(components["#document-fragment"].ToString());

                    tests.Add(new DataFileTestInfo(argumentList[0].ToString(), argumentList.ToArray()));
                    components = InitializeBuilders();
                }
            }
        }

        private Dictionary<string, StringBuilder> InitializeBuilders()
        {
            Dictionary<string, StringBuilder> components = new Dictionary<string, StringBuilder>();
            components.Add("#data", new StringBuilder());
            components.Add("#errors", new StringBuilder());
            components.Add("#document-fragment", new StringBuilder());
            components.Add("#document", new StringBuilder());
            return components;
        }

        private int ReadToNextMarker(string[] dataFileLines, int currentLineIndex, StringBuilder builder)
        {
            currentLineIndex++;
            string currentLine = dataFileLines[currentLineIndex];
            while (!currentLine.StartsWith("#") && currentLineIndex < dataFileLines.Length)
            {
                if (builder.Length > 0)
                {
                    builder.AppendLine();
                }

                builder.Append(dataFileLines[currentLineIndex]);
                currentLineIndex++;
                if (currentLineIndex < dataFileLines.Length)
                {
                    currentLine = dataFileLines[currentLineIndex];
                }
            }

            return currentLineIndex;
        }

        private ReadOnlyCollection<string> CreateExpectedErrorList(string expectedErrorList)
        {
            string[] errorStrings = expectedErrorList.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            List<string> errorList = new List<string>(errorStrings);
            return errorList.AsReadOnly();
        }
    }
}
